import { AccessLevel, Inject, SingletonProto } from "@eggjs/tegg";
import { BaseController } from "../../core/controller/BaseController";
import ClientConfig from "./ClientConfig";
import { AlmightyType, EggLogger, FbType, MsgType, OperationType, ReceiveType, UserType } from "typings/app";
import { ArrayUtils, ClientAutoMesUtils, ClientGetTokenUtils, StringUtils } from "..";
// import { Context } from "egg";

/**
 * 飞书消息工具
 * 
 * @author Jn
 * @version v0.0.1
 */
@SingletonProto({
    accessLevel: AccessLevel.PUBLIC
})
export class ClientSendMsgUtils extends BaseController {

    @Inject()
    logger: EggLogger

    @Inject()
    clientUtils: ClientAutoMesUtils

    @Inject()
    tokenUtils: ClientGetTokenUtils

    @Inject()
    // ctx: Context
    eggContextHandler: any;

    /**
     * 发送消息内容
     * @param receiveId 接收群体
     * @param appId appId
     * @param content 消息体
     * @param type 消息类型
     * @param receiveType 发送类型
     * @returns 
     */
    async SendAnyMsg(receiveId: string | string[], appId: string = ClientConfig.ApplicationRobot.appId, content: string = JSON.stringify({ "text": "消息测试" }), type: FbType = 'text', receiveType: ReceiveType = 'user_id') {
        if (!receiveId) {
            return this.error("缺失发送用户参数！")
        }

        if (StringUtils.IsArray(receiveId)) {
            if (receiveType == 'user_id') {
                if (receiveId.includes(",") && !ArrayUtils.IsArray(receiveId)) {
                    receiveId = (receiveId as string).split(",")
                }
                return await this.SendBatchMsg(receiveId as Array<string>, appId, content, type)
            } else if (receiveType == 'chat_id') {
                if (receiveId.includes(",") && !ArrayUtils.IsArray(receiveId)) {
                    receiveId = (receiveId as string).split(",")
                }
                let pro: any[] = [];
                for (let i = 0; i < receiveId.length; i++) {
                    const id = receiveId[i];
                    pro.push(this.SendSingleMsg(id, appId, content, type, receiveType))
                }
                return await Promise.all(pro)
            }
        } else {
            return await this.SendSingleMsg(receiveId as string, appId, content, type, receiveType);
        }
    }

    /**
     * 加急、撤销、Pin
     * @param messageId 消息ID
     * @param type 操作类型
     * @param appId AppId
     * @param receiveType 用户类型
     * @param userIds 用户Id
     * @param isPin 是否
     * @returns 
     */
    async AlmightyMes(messageId: string, type: AlmightyType, appId: string, receiveType: UserType, userIds: string[] | string, isRemove: boolean = false, emojiType: string = 'OK', reactionId: string) {
        if (!messageId) {
            return this.error("缺失消息ID！")
        }
        if (!type) {
            return this.error("缺失操作类型！")
        }
        if (!appId) {
            return this.error("缺失AppId！")
        }
        if (type.includes('urgent')) {
            return await this.BuzzMsg(messageId, appId, userIds, type as MsgType, receiveType)
        } else if (type.includes('delete')) {
            return await this.DeleteMsg(messageId, appId);
        } else if (type.includes('pins')) {
            return await this.PinsMsg(messageId, appId, isRemove)
        } else if (type.includes('reactions')) {
            return await this.ReactionsMsg(messageId, appId, isRemove, reactionId, emojiType)
        } else {
            return this.error("未定义操作类型！")
        }
    }

    /**
     * 回复、编辑消息
     * @param messageId 消息ID
     * @param appId AppId
     * @param content 消息体
     * @param type 消息类型
     */
    async OperationMes(messageId: string, appId: string, receiveType: OperationType, content: string = JSON.stringify({ "text": "消息测试" }), type: FbType = 'text') {
        if (!messageId) {
            return this.error("缺失消息ID！")
        }

        if (!appId) {
            return this.error("缺失AppId！")
        }

        if (!receiveType) {
            return this.error("缺失操作类型！")
        }

        if (receiveType == 'reply') {
            return await this.ReplyMsg(messageId, appId, content, type);
        } else if (receiveType == 'update') {
            return await this.UpdateMsg(messageId, appId, content, type);
        } else {
            return this.error("未定义操作类型！")
        }
    }

    /**
     * 发送单个消息内容
     * @param receiveId 接收群体
     * @param appId appId
     * @param content 消息体
     * @param type 消息类型
     * @param receiveType 发送类型
     * @returns 
     */
    async SendSingleMsg(receiveId: string, appId: string, content: string, type: string, receiveType: ReceiveType) {
        let token = '';

        try {
            token = await this.tokenUtils.InsideToken(appId);
        } catch (error) {
            return this.error("未获取到AppID配置！")
        }

        let SetMap = new Map()
            .set("interactive", content)
            .set("text", { "text": content })
            .set("post", content)
            .set('image', { "image_key": content })
            .set("share_chat", { "chat_id": content })
            .set("share_user", { "user_id": content })
            .set("audio", { "file_key": content })
            .set("media", content)
            .set("file", { "file_key": content })
            .set("sticker", { "file_key": content })
            .set("system", content)

        if (!SetMap.has(type)) {
            return this.error("未定义的消息类型！")
        }

        let res: any
        try {
            res = await this.clientUtils.client.im.message.create({
                params: {
                    receive_id_type: receiveType
                },
                data: {
                    receive_id: receiveId,
                    content: JSON.stringify(SetMap.get(type)),
                    msg_type: type
                }
            }, {
                headers: {
                    "Authorization": token,
                    "Access-Control-Allow-Origin": "*",
                    "Content-Type": "application/json",
                }
            })
        } catch (error) {
            return this.error("消息发送异常！")
        }
        this.logger.info(res)
        return this.success(res)
    }

    /**
     * 发送批量消息内容
     * @param receiveIds 接收群体
     * @param appId appId
     * @param content 消息体
     * @param type 消息类型
     * @returns 
     */
    async SendBatchMsg(receiveIds: Array<string>, appId: string, content: string, type: string) {
        let token = '';

        try {
            token = await this.tokenUtils.InsideToken(appId);
        } catch (error) {
            return this.error("未获取到AppID配置！")
        }

        let SetMap = new Map()
            .set("interactive", { "card": content })
            .set("text", {
                "content": {
                    "text": content
                }
            })
            .set("post", {
                "content": {
                    "post": content
                }
            })
            .set('image', {
                "content": {
                    "image_key": content
                }
            })
            .set("share_chat", {
                "content": {
                    "share_chat_id": content
                }
            })

        if (!SetMap.has(type)) {
            return this.error("未定义的消息类型！")
        }

        let res = ""

        // 请求头配置
        const config = {
            headers: {
                "Authorization": token,
                "Access-Control-Allow-Origin": "*",
                "Content-Type": "application/json",
            }
        }

        const data = {
            "user_ids": receiveIds,
            "msg_type": type,
            ...SetMap.get(type)
        }
        try {
            res = await this.eggContextHandler.app.axios.post(ClientConfig.FbConfig.PostMsgBatchUrl, data, config);
        } catch (error) {
            return this.error("批量消息发送异常！")
        }

        this.logger.info(res)
        return this.success(res)
    }

    /**
     * 加急消息
     * @param messageId 消息ID
     * @param appId AppId
     * @param userIds 用户群体
     * @param type 消息加急类型
     * @param receiveType 用户类型
     * @returns 
     */
    async BuzzMsg(messageId: string, appId: string, userIds: string[] | string, type: MsgType, receiveType: UserType) {

        let token = '';

        if (!userIds) {
            return this.error("加急消息需要传入用户Ids！")
        }

        if (!receiveType) {
            return this.error("加急消息需要传入用户类型！")
        }

        if (!StringUtils.IsArray(userIds)) {
            if (userIds.includes(",")) {
                userIds = (userIds as string).split(',')
            } else {
                userIds = [userIds as string]
            }
        }

        try {
            token = await this.tokenUtils.InsideToken(appId);
        } catch (error) {
            return this.error("未获取到AppID配置！")
        }

        let res: any;

        try {
            if (type === 'urgent_app') {
                res = await this.clientUtils.client.im.message.urgentApp({
                    data: {
                        user_id_list: userIds as string[]
                    },
                    params: {
                        user_id_type: receiveType,
                    },
                    path: {
                        message_id: messageId
                    }
                }, {
                    headers: {
                        "Authorization": token,
                        "Access-Control-Allow-Origin": "*",
                        "Content-Type": "application/json",
                    }
                })
            } else if (type === 'urgent_sms') {
                res = await this.clientUtils.client.im.message.urgentSms({
                    data: {
                        user_id_list: userIds as string[]
                    },
                    params: {
                        user_id_type: receiveType,
                    },
                    path: {
                        message_id: messageId
                    }
                }, {
                    headers: {
                        "Authorization": token,
                        "Access-Control-Allow-Origin": "*",
                        "Content-Type": "application/json",
                    }
                })
            } else if (type === 'urgent_phone') {
                res = await this.clientUtils.client.im.message.urgentPhone({
                    data: {
                        user_id_list: userIds as string[]
                    },
                    params: {
                        user_id_type: receiveType,
                    },
                    path: {
                        message_id: messageId
                    }
                }, {
                    headers: {
                        "Authorization": token,
                        "Access-Control-Allow-Origin": "*",
                        "Content-Type": "application/json",
                    }
                })
            } else {
                return this.error("消息加急异常！")
            }
        } catch (error) {
            return this.error("消息加急异常！")
        }
        this.logger.info(res)
        return this.success(res)

    }

    /**
     * 撤销消息
     * @param messageId 消息ID
     * @param appId AppId
     * @returns 
     */
    async DeleteMsg(messageId: string, appId: string) {

        let token = '';

        try {
            token = await this.tokenUtils.InsideToken(appId);
        } catch (error) {
            return this.error("未获取到AppID配置！")
        }

        let res: any;

        try {
            if (messageId.startsWith('bm-')) {
                res = await this.clientUtils.client.im.v1.batchMessage.delete({
                    path: {
                        batch_message_id: messageId
                    }
                }, {
                    headers: {
                        "Authorization": token,
                        "Access-Control-Allow-Origin": "*",
                        "Content-Type": "application/json",
                    }
                })

            } else if (messageId.startsWith('om_')) {
                res = await this.clientUtils.client.im.message.delete({
                    path: {
                        message_id: messageId
                    }
                }, {
                    headers: {
                        "Authorization": token,
                        "Access-Control-Allow-Origin": "*",
                        "Content-Type": "application/json",
                    }
                })
            } else {
                return this.error("消息撤销异常！")
            }
        } catch (error) {
            return this.error("消息撤销异常！")
        }
        this.logger.info(res)
        return this.success(res)

    }

    /**
     * Pin消息
     * @param messageId 消息ID
     * @param appId AppId
     * @param isPin 是否Pin
     * @returns 
     */
    async PinsMsg(messageId: string, appId: string, isPin: boolean = false) {

        let token = '';

        try {
            token = await this.tokenUtils.InsideToken(appId);
        } catch (error) {
            return this.error("未获取到AppID配置！")
        }

        let res: any;

        try {
            if (messageId.startsWith('om_')) {
                if (!isPin) {
                    res = await this.clientUtils.client.im.pin.create({
                        data: {
                            message_id: messageId
                        }
                    }, {
                        headers: {
                            "Authorization": token,
                            "Access-Control-Allow-Origin": "*",
                            "Content-Type": "application/json",
                        }
                    })
                } else {
                    res = await this.clientUtils.client.im.pin.delete({
                        path: {
                            message_id: messageId
                        }
                    }, {
                        headers: {
                            "Authorization": token,
                            "Access-Control-Allow-Origin": "*",
                            "Content-Type": "application/json",
                        }
                    })
                }
            } else if (messageId.startsWith('bm-')) {
                return this.error("消息加Pin只能加om_xx")
            }
        } catch (error) {
            return this.error("消息加Pin异常！")
        }
        this.logger.info(res)
        return this.success(res)
    }

    /**
     * 表情回复
     * @param messageId 消息ID
     * @param appId AppId
     * @param isRemove 是否删除
     * @param reactionId 资源ID
     * @param emojiType 表情
     * @returns 
     */
    async ReactionsMsg(messageId: string, appId: string, isRemove: boolean = false, reactionId: string, emojiType: string) {

        let token = '';

        if (isRemove) {
            if (!reactionId) {
                return this.error("请填写删除表情回复的资源ID")
            }
        }

        try {
            token = await this.tokenUtils.InsideToken(appId);
        } catch (error) {
            return this.error("未获取到AppID配置！")
        }

        let res: any;

        try {
            if (messageId.startsWith('om_')) {
                if (!isRemove) {
                    res = await this.clientUtils.client.im.messageReaction.create({
                        data: {
                            reaction_type: {
                                emoji_type: emojiType
                            }
                        },
                        path: {
                            message_id: messageId
                        }
                    }, {
                        headers: {
                            "Authorization": token,
                            "Access-Control-Allow-Origin": "*",
                            "Content-Type": "application/json",
                        }
                    })
                } else {
                    res = await this.clientUtils.client.im.messageReaction.delete({
                        path: {
                            message_id: messageId,
                            reaction_id: reactionId
                        }
                    }, {
                        headers: {
                            "Authorization": token,
                            "Access-Control-Allow-Origin": "*",
                            "Content-Type": "application/json",
                        }
                    })
                }
            } else if (messageId.startsWith('bm-')) {
                return this.error("表情回复只能加om_xx")
            }
        } catch (error) {
            return this.error("表情回复异常！")
        }
        this.logger.info(res)
        return this.success(res)
    }

    /**
     * 消息回复
     * @param messageId 消息ID
     * @param appId AppId
     * @param content 消息体
     * @param appId 消息类型
     * @returns 
     */
    async ReplyMsg(messageId: string, appId: string, content: string, type: string) {

        let token = '';

        try {
            token = await this.tokenUtils.InsideToken(appId);
        } catch (error) {
            return this.error("未获取到AppID配置！")
        }

        let SetMap = new Map()
            .set("interactive", content)
            .set("text", { "text": content })
            .set("post", content)
            .set('image', { "image_key": content })
            .set("share_chat", { "chat_id": content })
            .set("share_user", { "user_id": content })
            .set("audio", { "file_key": content })
            .set("media", content)
            .set("file", { "file_key": content })
            .set("sticker", { "file_key": content })
            .set("system", content)

        if (!SetMap.has(type)) {
            return this.error("未定义的消息类型！")
        }

        let res: any;

        try {
            if (messageId.startsWith('om_')) {
                res = await this.clientUtils.client.im.message.reply({
                    path: {
                        message_id: messageId
                    },
                    data: {
                        content: JSON.stringify(SetMap.get(type)),
                        msg_type: type
                    }
                }, {
                    headers: {
                        "Authorization": token,
                        "Access-Control-Allow-Origin": "*",
                        "Content-Type": "application/json",
                    }
                })
            } else if (messageId.startsWith('bm-')) {
                return this.error("消息回复只能加om_xx")
            }
        } catch (error) {
            return this.error("消息回复异常！")
        }
        this.logger.info(res)
        return this.success(res)
    }

    /**
     * 编辑消息
     * @param messageId 消息ID
     * @param appId AppId
     * @returns 
     */
    async UpdateMsg(messageId: string, appId: string, content: string, type: string) {

        let token = '';

        try {
            token = await this.tokenUtils.InsideToken(appId);
        } catch (error) {
            return this.error("未获取到AppID配置！")
        }

        let SetMap = new Map()
            .set("text", { "text": content })
            .set("post", content)

        if (!SetMap.has(type)) {
            return this.error("未定义的消息类型！")
        }

        let res: any;

        try {
            if (messageId.startsWith('om_')) {
                res = await this.clientUtils.client.im.message.update({
                    path: {
                        message_id: messageId
                    },
                    data: {
                        content: JSON.stringify(SetMap.get(type)),
                        msg_type: type
                    }
                }, {
                    headers: {
                        "Authorization": token,
                        "Access-Control-Allow-Origin": "*",
                        "Content-Type": "application/json",
                    }
                })
            } else if (messageId.startsWith('bm-')) {
                return this.error("编辑消息只能加om_xx")
            }
        } catch (error) {
            return this.error("编辑消息异常！")
        }
        this.logger.info(res)
        return this.success(res)
    }

    /**
     * 循环获取多维表格数据
     * @param appToken apptoken
     * @param tableId 表格id
     * @param token token
     * @returns 
     */
    async readDocsData(appToken: string, tableId: string, params?: any, appId?: string) {
        /** 下一页标记 */
        let page_token: undefined | string;
        /** 是否有下一页 */
        let hasMore: boolean = true;
        /** 返回数据 */
        let items: any[] = [];
        let token: string = await this.tokenUtils.InsideToken(appId ?? "appId");
        while (hasMore) {
            const { data } = await this.clientUtils.client.bitable.appTableRecord.search({
                data: params,
                path: {
                    app_token: appToken,
                    table_id: tableId
                },
                params: {
                    page_token: page_token
                }
            }, {
                headers: {
                    "Authorization": token,
                    "Access-Control-Allow-Origin": "*",
                    "Content-Type": "application/json",
                }
            })
            hasMore = data?.has_more!;
            items.push(...(data?.items as any).filter((d: any) => Object.keys(d.fields).length != 0));
            page_token = data?.page_token;
        }
        return items
    }

    /**
     * 批量新增记录
     * @param appToken 
     * @param tableId 
     * @param data 
     * @param appId 
     * @returns 
     */
    async insertDocsDatas(appToken: string, tableId: string, data: any, appId?: string) {
        let token: string = await this.tokenUtils.InsideToken(appId ?? "appId");
        return await this.clientUtils.client.bitable.appTableRecord.batchCreate({
            data: data,
            path: {
                app_token: appToken,
                table_id: tableId
            }
        }, {
            headers: {
                "Authorization": token,
                "Access-Control-Allow-Origin": "*",
                "Content-Type": "application/json",
            }
        })
    }

    /**
     * 新增单条记录
     * @param appToken 
     * @param tableId 
     * @param data 
     * @param appId 
     * @returns 
     */
    async insertDocsData(appToken: string, tableId: string, data: any, appId?: string) {
        let token: string = await this.tokenUtils.InsideToken(appId ?? "appId");
        return await this.clientUtils.client.bitable.appTableRecord.create({
            data: data,
            path: {
                app_token: appToken,
                table_id: tableId
            }
        }, {
            headers: {
                "Authorization": token,
                "Access-Control-Allow-Origin": "*",
                "Content-Type": "application/json",
            }
        })
    }

    /**
     * 批量更新记录
     * @param appToken 
     * @param tableId 
     * @param data 
     * @param appId 
     * @returns 
     */
    async updateDocsDatas(appToken: string, tableId: string, data: any, appId?: string) {
        let token: string = await this.tokenUtils.InsideToken(appId ?? "appId");
        return await this.clientUtils.client.bitable.appTableRecord.batchUpdate({
            data: data,
            path: {
                app_token: appToken,
                table_id: tableId
            }
        }, {
            headers: {
                "Authorization": token,
                "Access-Control-Allow-Origin": "*",
                "Content-Type": "application/json",
            }
        })
    }

    /**
     * 更新记录
     * @param appToken 
     * @param tableId 
     * @param recordId 
     * @param data 
     * @param appId 
     * @returns 
     */
    async updateDocsData(appToken: string, tableId: string, recordId: string, data: any, appId?: string) {
        let token: string = await this.tokenUtils.InsideToken(appId ?? "appId");
        return await this.clientUtils.client.bitable.appTableRecord.update({
            data: data,
            path: {
                app_token: appToken,
                table_id: tableId,
                record_id: recordId
            }
        }, {
            headers: {
                "Authorization": token,
                "Access-Control-Allow-Origin": "*",
                "Content-Type": "application/json",
            }
        })
    }

    /**
     * 批量删除记录
     * @param appToken 
     * @param tableId 
     * @param data 
     * @param appId 
     * @returns 
     */
    async deleteDocsDatas(appToken: string, tableId: string, data: any, appId?: string) {
        let token: string = await this.tokenUtils.InsideToken(appId ?? "appId");
        return await this.clientUtils.client.bitable.appTableRecord.batchDelete({
            data: data,
            path: {
                app_token: appToken,
                table_id: tableId
            }
        }, {
            headers: {
                "Authorization": token,
                "Access-Control-Allow-Origin": "*",
                "Content-Type": "application/json",
            }
        })
    }

    /**
     * 删除记录
     * @param appToken 
     * @param tableId 
     * @param recordId 
     * @param appId 
     * @returns 
     */
    async deleteDocsData(appToken: string, tableId: string, recordId: string, appId?: string) {
        let token: string = await this.tokenUtils.InsideToken(appId ?? "appId");
        return await this.clientUtils.client.bitable.appTableRecord.delete({
            path: {
                app_token: appToken,
                table_id: tableId,
                record_id: recordId
            }
        }, {
            headers: {
                "Authorization": token,
                "Access-Control-Allow-Origin": "*",
                "Content-Type": "application/json",
            }
        })
    }
}